import workerpool from "workerpool";
import { isDev, isPro } from "@/setting/env";
import type { Pool } from "workerpool";
import type TDepts from "./modules";

const workerpoolMap = new Map<string, Pool>();

export const getWorkerPool = (workerName: string): Pool => {
    if (workerpoolMap.has(workerName)) return workerpoolMap.get(workerName) as Pool;
    throw new Error(`Worker ${workerName} not found`);
};

const patchWorker = () => {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    if (globalThis.Worker && !(globalThis.Worker as any).patched) {
        class PatchedWorker extends Worker {
            static patched = true;
            constructor(scriptURL: string | URL, options?: WorkerOptions) {
                super(scriptURL, Object.assign({}, options, { type: "module" }));
            }
        }
        globalThis.Worker = PatchedWorker;
    }
};

const initializeWorker = (workerName: string): Pool => {
    if (workerpoolMap.has(workerName)) return workerpoolMap.get(workerName) as Pool;
    patchWorker();
    // 开发环境
    if (isDev)
        workerpoolMap.set(
            workerName,
            workerpool.pool(new URL(`./defaultWorker.ts?worker_file`, import.meta.url).href)
        );
    // 生产环境
    if (isPro) workerpoolMap.set(workerName, workerpool.pool("./worker.bundle.js"));

    return workerpoolMap.get(workerName) as Pool;
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export async function workerChunk<T extends any[], R>(
    fn: (depts: typeof TDepts, ...args: T) => Promise<R> | R,
    ...args: T
) {
    const worker = initializeWorker(workerChunk.name);
    return worker.exec("runWithDepts", [String(fn)].concat(args));
}
